import datetime
import pytz

import coin.exchange.base.kr_rest.public_client_base as pubcb
import coin.exchange.binance_futures.kr_rest.native_public_client as npubc
from coin.exchange.binance_futures.kr_rest.futures_product import BinanceFuturesProduct
from coin.proto.coin_market_query_pb2 import (
    ProductKline,
    ProductKlineElement)

class BinanceFuturesFeedParser(object):
  @staticmethod
  def parse_native_kline(update_msg, product, kline_period):
    """Sample kline response:
    [
      [
        1591258320000,          // Open time
        "9640.7",               // Open
        "9642.4",               // High
        "9640.6",               // Low
        "9642.0",               // Close (or latest price)
        "206",                  // Volume
        1591258379999,          // Close time
        "2.13660389",           // Base asset volume
        48,                     // Number of trades
        "119",                  // Taker buy volume
        "1.23424865",           // Taker buy base asset volume
        "0"                         // Ignore.
      ]
    ]
    """
    klines = update_msg
    kline_group = []
    for kline in klines:
      volume = float(kline[5])
      buy_volume = float(kline[9])
      sell_volume = volume - buy_volume
      product_kline = ProductKlineElement(kline_timestamp=int(kline[0] * 1e+6),
                                          open=float(kline[1]),
                                          high=float(kline[2]),
                                          low=float(kline[3]),
                                          close=float(kline[4]),
                                          volume=volume,
                                          buy_volume=buy_volume,
                                          sell_volume=sell_volume,
                                          turnover=float(kline[7]))
      kline_group.append(product_kline)
    return ProductKline(
        symbol=product.symbol,
        native_symbol=product.native_symbol,
        exchange='Binance',
        market_type='Futures',
        kline_period=kline_period,
        klines=kline_group,
    )

class BinanceFuturesPublicClient(pubcb.PublicClientBase):
  ProductType = BinanceFuturesProduct

  def __init__(self):
    self.npubc = npubc.BinanceFuturesNativePublicClient()

  def query_history_kline_impl(self, product, kline_period, start_time, end_time):
    native_symbol = product.native_symbol
    start_time = start_time.replace(tzinfo=pytz.UTC)
    end_time = end_time.replace(tzinfo=pytz.UTC)
    update = self.npubc.get_history_kline(
        native_symbol, kline_period, start_time=start_time, end_time=end_time)
    update.msg = BinanceFuturesFeedParser.parse_native_kline(
        update.msg, product, kline_period)
    return update

  def query_level_book_impl(self, product):
    raise NotImplementedError("Binance futures query level book Not Implemented")


if __name__ == "__main__":
  client = BinanceFuturesPublicClient()
  start_time = datetime.datetime(2022, 5, 5).replace(tzinfo=pytz.UTC)
  end_time = datetime.datetime(2022, 5, 5, 2).replace(tzinfo=pytz.UTC)
  print(client.query_history_kline(
      BinanceFuturesProduct.FromStr('BTC-USD.PERPETUAL'), '1h', start_time, end_time).msg)
